{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "my_arr = np.arange(1000000)\n",
    "my_list = list(range(1000000))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "NumPy的ndarray:一种多维数组对象 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.29582904, -0.16817497, -0.33855948],\n",
       "       [ 1.64273684, -1.51359119, -1.26057131]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 生成一些数组\n",
    "data = np.random.randn(2,3)\n",
    "data\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ -2.9582904 ,  -1.68174965,  -3.38559476],\n",
       "       [ 16.42736836, -15.1359119 , -12.60571309]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 进行数学运算\n",
    "# 乘法  所有元素都乘了一个数\n",
    "data*10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.59165808, -0.33634993, -0.67711895],\n",
       "       [ 3.28547367, -3.02718238, -2.52114262]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 加法  每个对应元素相加\n",
    "data+data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 3)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.shape\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6. , 7.5, 8. , 0. , 1. ])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建数组最简单的办法就是使⽤array函数。它接受⼀切序列型的对象（包括其他数组），\n",
    "# 然后产⽣⼀个新的含有传⼊数据的NumPy数组。以⼀个列表的转换为例：\n",
    "data1 = [6,7.5,8,0,1]\n",
    "arr1 = np.array(data1)\n",
    "arr1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3, 4],\n",
       "       [5, 6, 7, 8]])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data2 = [[1,2,3,4],[5,6,7,8]]\n",
    "arr2 = np.array(data2)\n",
    "arr2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2.ndim"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 4)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# np.array会尝试为新建的这个数组推断出⼀个较为合适的数据类型。数据类型保存在⼀个特殊的dtype对象中。\n",
    "# ⽐如说，在上⾯的两个例⼦中，我们有：\n",
    "arr1.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int32')"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# zeros和ones分别可以创建指定⻓度或形状的全0或全1数组。\n",
    "# empty可以创建⼀个没有任何具体值的数组。\n",
    "# 要⽤这些⽅法创建多维数组，只需传⼊⼀个表示形状的元组即可：\n",
    "np.zeros(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros((3,6))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1., 1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1., 1., 1.],\n",
       "       [1., 1., 1., 1., 1., 1.]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones((3,6))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[6.21714237e-312, 2.47032823e-322],\n",
       "        [0.00000000e+000, 0.00000000e+000],\n",
       "        [6.23053953e-307, 5.64233733e-067]],\n",
       "\n",
       "       [[7.48397044e-091, 6.75217019e-067],\n",
       "        [1.55196193e+184, 7.61073870e-042],\n",
       "        [3.99910963e+252, 1.37961302e-306]]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.empty((2,3,2))  # empty可以创建的是⼀个没有任何具体值的数组，不是0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# arange是python中内置函数range的数组版\n",
    "np.arange(15)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ndarray的数据类型dtype（数据类型）是⼀个特殊的对象，\n",
    "# 它含有ndarray将⼀块内存解释为特定数据类型所需的信息：\n",
    "arr1 = np.array([1,2,3],dtype=np.float64)\n",
    "arr2 = np.array([1,2,3],dtype=np.int32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr1.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int32')"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int32')"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 可以通过ndarray的astype⽅法明确地将⼀个数组从⼀个dtype转换成另⼀个dtype：\n",
    "arr = np.array([1, 2, 3, 4, 5])\n",
    "arr.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float_arr = arr.astype(np.float64)\n",
    "float_arr.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 3.7, -1.2, -2.6,  0.5, 12.9])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在上例中，整数被转换成了浮点数。\n",
    "# 如果将浮点数转换成整数，则⼩数部分将会被截取删除：\n",
    "arr = np.array([3.7,-1.2,-2.6,0.5,12.9])\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 3, -1, -2,  0, 12])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.astype(np.int32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['1.25', '-9.6', '0.5'], dtype='<U4')"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 如果某字符串数组表示的全是数字，也可以⽤astype将其转换为数值形式：\n",
    "numeric_strings = np.array(['1.25','-9.6','0.5'])\n",
    "numeric_strings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.25, -9.6 ,  0.5 ])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "numeric_strings.astype(np.float)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ NumPy数组的运算\n",
    "数组很重要，因为它使你不⽤编写循环即可对数据执⾏批量运\n",
    "算。NumPy⽤户称其为⽮量化（vectorization）。⼤⼩相等的数\n",
    "组之间的任何算术运算都会将运算应⽤到元素级：\n",
    "+ 不同⼤⼩的数组之间的运算叫做⼴播（broadcasting）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([[1,2,3],[4,5,6]])\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  4,  9],\n",
       "       [16, 25, 36]])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 数组相乘\n",
    "arr*arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0],\n",
       "       [0, 0, 0]])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 数组相减\n",
    "arr-arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.        , 0.5       , 0.33333333],\n",
       "       [0.25      , 0.2       , 0.16666667]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 数组与标量的算术运算会将标量值传播到各个元素\n",
    "# 除以一个数\n",
    "1/arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  4,  1],\n",
       "       [ 7,  2, 12]])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 大小相同的数组之间的比较会生成布尔值数组\n",
    "arr2 = np.array([[0,4,1],[7,2,12]])\n",
    "arr2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False,  True, False],\n",
       "       [ True, False,  True]])"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2 > arr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 基本的索引和切片"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# NumPy数组的索引是⼀个内容丰富的主题，因为选取数据⼦集或单个元素的⽅式有很多。\n",
    "# ⼀维数组很简单。从表⾯上看，它们跟Python列表的功能差不多：\n",
    "arr = np.arange(10)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 6, 7])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[5:8]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 如上所示，当你将⼀个标量值赋值给⼀个切⽚时（如arr[5:8]=12），该值会⾃动传播（也就说后⾯将会讲到的“⼴播”）到整个选区。\n",
    "# 跟列表最重要的区别在于，数组切⽚是原始数组的视图。这意味着数据不会被复制，视图上的任何修改都会直接反映到源数组上。\n",
    "arr[5:8]=12 \n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([12, 12, 12])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 作为例⼦，先创建⼀个arr的切⽚：\n",
    "arr_slice =arr[5:8]\n",
    "arr_slice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,\n",
       "           9])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 现在，当我修稿arr_slice中的值，变动也会体现在原始数组arr中：\n",
    "arr_slice[1] = 12345\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 切⽚[ : ]会给数组中的所有值赋值：\n",
    "arr_slice[:] = 64\n",
    "arr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果你刚开始接触NumPy，可能会对此感到惊讶（尤其是当你\n",
    "曾经⽤过其他热衷于复制数组数据的编程语⾔）。由于NumPy\n",
    "的设计⽬的是处理⼤数据，所以你可以想象⼀下，假如NumPy\n",
    "坚持要将数据复制来复制去的话会产⽣何等的性能和内存问题。\n",
    "注意：如果你想要得到的是ndarray切⽚的⼀份副本⽽⾮视\n",
    "图，就需要明确地进⾏复制操作，例如arr[5:8].copy()。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#对于⾼维度数组，能做的事情更多。在⼀个⼆维数组中，各索引位置上的元素不再是标量⽽是⼀维数组：\n",
    "arr2d = np.array([[1,2,3],[4,5,6],[7,8,9]])\n",
    "arr2d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4, 5, 6])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 因此，可以对各个元素进⾏递归访问，但这样需要做的事情有点多。\n",
    "# 你可以传⼊⼀个以逗号隔开的索引列表来选取单个元素。也就是说，下⾯两种⽅式是等价的：\n",
    "arr2d[0][2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[0,2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 1,  2,  3],\n",
       "        [ 4,  5,  6]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在多维数组中，如果省略了后⾯的索引，则返回对象会是⼀个维度低⼀点的ndarray（它含有⾼⼀级维度上的所有数据）。\n",
    "# 因此，在2×2×3数组arr3d中：\n",
    "arr3d = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])\n",
    "arr3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 标量值和数组都可以被赋值给arr3d[0]：\n",
    "old_values =arr3d[0].copy()\n",
    "old_values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[42, 42, 42],\n",
       "        [42, 42, 42]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d[0] = 42\n",
    "arr3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 1,  2,  3],\n",
       "        [ 4,  5,  6]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d[0] = old_values\n",
    "arr3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7, 8, 9])"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 相似的，arr3d[1,0]可以访问索引以(1,0)开头的那些值（以⼀维数组的形式返回）：\n",
    "arr3d[1,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 7,  8,  9],\n",
       "       [10, 11, 12]])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 虽然是⽤两步进⾏索引的，表达式是相同的：\n",
    "x = arr3d[1]\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7, 8, 9])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "切⽚索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# ndarray的切⽚语法跟Python列表这样的⼀维对象差不多：\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1,  2,  3,  4, 64])"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[1:6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对于之前的⼆维数组arr2d，其切⽚⽅式稍显不同：\n",
    "arr2d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 可以看出，它是沿着第0轴（即第⼀个轴）切⽚的。也就是说，切⽚是沿着⼀个轴向选取元素的。\n",
    "# 表达式arr2d[:2]可以被认为是“选取arr2d的前两⾏”。\n",
    "arr2d[:2] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 3],\n",
       "       [5, 6]])"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 你可以⼀次传⼊多个切⽚，就像传⼊多个索引那样：\n",
    "arr2d[:2,1:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4, 5])"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 第⼆⾏的前两列：\n",
    "arr2d[1,:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([3, 6])"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 择第三列的前两⾏：\n",
    "arr2d[:2,2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1],\n",
       "       [4],\n",
       "       [7]])"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 。注意，“只有冒号”表示选取整个轴，因此你可以像下⾯这样只对⾼维轴进⾏切⽚：\n",
    "arr2d[:,:1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 0, 0],\n",
       "       [4, 0, 0],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对切⽚表达式的赋值操作也会被扩散到整个选区：\n",
    "arr2d[:2,1:] = 0\n",
    "arr2d"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 布尔型索引\n",
    "来看这样⼀个例⼦，假设我们有⼀个⽤于存储数据的数组以及⼀\n",
    "个存储姓名的数组（含有重复项）。在这⾥，我将使⽤\n",
    "numpy.random中的randn函数⽣成⼀些正态分布的随机数据："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4')"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])\n",
    "names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.94028769,  2.06539879, -0.38916884,  1.48317874],\n",
       "       [ 0.41614868, -0.04162171,  1.14641478, -0.9927943 ],\n",
       "       [-0.83227708,  0.80391888,  1.05759875,  1.05521247],\n",
       "       [ 0.61387986,  0.09380628, -1.21986185, -0.84697332],\n",
       "       [-0.10172819,  0.13144893, -0.07816702, -2.59003274],\n",
       "       [-0.0639491 , -0.07121933, -2.35744406,  1.58456182],\n",
       "       [ 0.98226205, -0.44812156, -0.27243958,  1.0046149 ]])"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = np.random.randn(7,4)\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 假设每个名字都对应data数组中的⼀⾏，⽽我们想要选出对应于名字\"Bob\"的所有⾏。\n",
    "# 跟算术运算⼀样，数组的⽐较运算（如==）也是⽮量化的。\n",
    "# 因此，对names和字符串\"Bob\"的⽐较运算将会产⽣⼀个布尔型数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True, False, False,  True, False, False, False])"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "names == 'Bob'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.94028769,  2.06539879, -0.38916884,  1.48317874],\n",
       "       [ 0.61387986,  0.09380628, -1.21986185, -0.84697332]])"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 这个布尔型数组可⽤于数组索引：\n",
    "data[names == 'Bob']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.38916884,  1.48317874],\n",
       "       [-1.21986185, -0.84697332]])"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 下⾯的例⼦，我选取了names\t==\t'Bob'的⾏，并索引了列：\n",
    "data[names == 'Bob',2:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.48317874, -0.84697332])"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[names == 'Bob',3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False,  True,  True, False,  True,  True,  True])"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 要选择除\"Bob\"以外的其他值，既可以使⽤不等于符号（!=），也可以通过~对条件进⾏否定：\n",
    "names != 'Bob'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.41614868, -0.04162171,  1.14641478, -0.9927943 ],\n",
       "       [-0.83227708,  0.80391888,  1.05759875,  1.05521247],\n",
       "       [-0.10172819,  0.13144893, -0.07816702, -2.59003274],\n",
       "       [-0.0639491 , -0.07121933, -2.35744406,  1.58456182],\n",
       "       [ 0.98226205, -0.44812156, -0.27243958,  1.0046149 ]])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#data[names != 'Bob'] # 或者下面这种方式也可以\n",
    "data[~(names == 'Bob')]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.41614868, -0.04162171,  1.14641478, -0.9927943 ],\n",
       "       [-0.83227708,  0.80391888,  1.05759875,  1.05521247],\n",
       "       [-0.10172819,  0.13144893, -0.07816702, -2.59003274],\n",
       "       [-0.0639491 , -0.07121933, -2.35744406,  1.58456182],\n",
       "       [ 0.98226205, -0.44812156, -0.27243958,  1.0046149 ]])"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# ~ 操作符⽤来反转条件很好⽤：\n",
    "cond = names == 'Bob'\n",
    "data[~cond]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True, False,  True,  True,  True, False, False])"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 选取这三个名字中的两个需要组合应⽤多个布尔条件，使⽤&（和）、|（或）之类的布尔算术运算符即可\n",
    "mask = (names == 'Bob')|(names == 'Will')\n",
    "mask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.94028769,  2.06539879, -0.38916884,  1.48317874],\n",
       "       [-0.83227708,  0.80391888,  1.05759875,  1.05521247],\n",
       "       [ 0.61387986,  0.09380628, -1.21986185, -0.84697332],\n",
       "       [-0.10172819,  0.13144893, -0.07816702, -2.59003274]])"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[mask]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 通过布尔型索引选取数组中的数据，将总是创建数据的副本，即使返回⼀模⼀样的数组也是如此。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.94028769, 2.06539879, 0.        , 1.48317874],\n",
       "       [0.41614868, 0.        , 1.14641478, 0.        ],\n",
       "       [0.        , 0.80391888, 1.05759875, 1.05521247],\n",
       "       [0.61387986, 0.09380628, 0.        , 0.        ],\n",
       "       [0.        , 0.13144893, 0.        , 0.        ],\n",
       "       [0.        , 0.        , 0.        , 1.58456182],\n",
       "       [0.98226205, 0.        , 0.        , 1.0046149 ]])"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 通过布尔型数组设置值是⼀种经常⽤到的⼿段。为了将data中的所有负值都设置为0，我们只需：\n",
    "data[data<0] = 0\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[7.        , 7.        , 7.        , 7.        ],\n",
       "       [0.41614868, 0.        , 1.14641478, 0.        ],\n",
       "       [7.        , 7.        , 7.        , 7.        ],\n",
       "       [7.        , 7.        , 7.        , 7.        ],\n",
       "       [7.        , 7.        , 7.        , 7.        ],\n",
       "       [0.        , 0.        , 0.        , 1.58456182],\n",
       "       [0.98226205, 0.        , 0.        , 1.0046149 ]])"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 通过⼀维布尔数组设置整⾏或列的值也很简单：\n",
    "data[names != 'Joe'] = 7\n",
    "data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 花式索引\n",
    "花式索引（Fancy indexing）是⼀个NumPy术语，它指的是利⽤\n",
    "整数数组进⾏索引。假设我们有⼀个8×4数组：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 6.21714481e-312,  1.08694442e-321,  0.00000000e+000,\n",
       "         0.00000000e+000],\n",
       "       [ 2.07955588e-312,  1.16095484e-028, -4.33511922e-232,\n",
       "        -2.03580528e+176],\n",
       "       [-1.27984077e-194, -1.23488152e-034, -2.42545774e+195,\n",
       "        -2.04692564e-267],\n",
       "       [-6.09845519e-131, -1.02297252e+181, -4.88581821e-045,\n",
       "        -1.36416866e-010],\n",
       "       [-4.22286948e-248, -1.08046591e+229, -9.18926206e-262,\n",
       "        -4.57560560e-179],\n",
       "       [-9.21889340e+190, -5.26157217e-228, -1.01468904e-241,\n",
       "         2.06887484e+161],\n",
       "       [ 2.11988410e+161,  3.14439244e-120,  4.42534337e+222,\n",
       "         2.18072757e-153],\n",
       "       [ 9.14144997e+135,  4.50620087e-144,  4.82412328e+228,\n",
       "         1.04718130e-142]])"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.empty((8,4))\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 6.21714481e-312,  1.08694442e-321,  0.00000000e+000,\n",
       "         0.00000000e+000],\n",
       "       [ 2.07955588e-312,  1.16095484e-028, -4.33511922e-232,\n",
       "        -2.03580528e+176],\n",
       "       [-1.27984077e-194, -1.23488152e-034, -2.42545774e+195,\n",
       "        -2.04692564e-267],\n",
       "       [-6.09845519e-131, -1.02297252e+181, -4.88581821e-045,\n",
       "        -1.36416866e-010],\n",
       "       [-4.22286948e-248, -1.08046591e+229, -9.18926206e-262,\n",
       "        -4.57560560e-179],\n",
       "       [-9.21889340e+190, -5.26157217e-228, -1.01468904e-241,\n",
       "         2.06887484e+161],\n",
       "       [ 2.11988410e+161,  3.14439244e-120,  4.42534337e+222,\n",
       "         2.18072757e-153],\n",
       "       [ 9.14144997e+135,  4.50620087e-144,  4.82412328e+228,\n",
       "         1.04718130e-142]])"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "for i in range(8):\n",
    "    arr[i]\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-4.22286948e-248, -1.08046591e+229, -9.18926206e-262,\n",
       "        -4.57560560e-179],\n",
       "       [-6.09845519e-131, -1.02297252e+181, -4.88581821e-045,\n",
       "        -1.36416866e-010],\n",
       "       [-1.27984077e-194, -1.23488152e-034, -2.42545774e+195,\n",
       "        -2.04692564e-267],\n",
       "       [ 2.07955588e-312,  1.16095484e-028, -4.33511922e-232,\n",
       "        -2.03580528e+176]])"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 为了以特定顺序选取⾏⼦集，只需传⼊⼀个⽤于指定顺序的整数列表或ndarray即可：\n",
    "arr[[4,3,2,1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 9.14144997e+135,  4.50620087e-144,  4.82412328e+228,\n",
       "         1.04718130e-142],\n",
       "       [ 2.11988410e+161,  3.14439244e-120,  4.42534337e+222,\n",
       "         2.18072757e-153],\n",
       "       [-9.21889340e+190, -5.26157217e-228, -1.01468904e-241,\n",
       "         2.06887484e+161]])"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 这段代码确实达到我们的要求了！使⽤负数索引将会从末尾开始选取⾏：\n",
    "arr[[-1,-2,-3]]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3],\n",
       "       [ 4,  5,  6,  7],\n",
       "       [ 8,  9, 10, 11],\n",
       "       [12, 13, 14, 15],\n",
       "       [16, 17, 18, 19],\n",
       "       [20, 21, 22, 23],\n",
       "       [24, 25, 26, 27],\n",
       "       [28, 29, 30, 31]])"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# ⼀次传⼊多个索引数组会有⼀点特别。它返回的是⼀个⼀维数组，其中的元素对应各个索引元组：\n",
    "arr = np.arange(32).reshape((8,4))\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 4, 23, 29, 10])"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[[1,5,7,2],[0,3,1,2]]   # 选出的是位置(1,0)、(5,3)、(7,1)和(2,2)的元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  7,  5,  6],\n",
       "       [20, 23, 21, 22],\n",
       "       [28, 31, 29, 30],\n",
       "       [ 8, 11,  9, 10]])"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 得到矩形区域的方法，注意括号，跟上面的区别\n",
    "arr[[1,\t5,\t7,\t2]][:,\t[0,\t3,\t1,\t2]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 数组转置和轴对换\n",
    "+ 转置是重塑的⼀种特殊形式\n",
    "+ 它返回的是源数据的视图（不会进⾏任何复制操作）。\n",
    "+ 数组不仅有transpose⽅法，还有⼀个特殊的T(转置)属性：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2,  3,  4],\n",
       "       [ 5,  6,  7,  8,  9],\n",
       "       [10, 11, 12, 13, 14]])"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(15).reshape((3,5))\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10],\n",
       "       [ 1,  6, 11],\n",
       "       [ 2,  7, 12],\n",
       "       [ 3,  8, 13],\n",
       "       [ 4,  9, 14]])"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.461359  , -0.41235924,  0.49507227],\n",
       "       [-2.27664382,  1.45213595, -3.04349892],\n",
       "       [-1.61979519, -1.45559096, -0.26871607],\n",
       "       [-0.4057907 ,  1.22542628, -1.24950898],\n",
       "       [-0.13756518, -1.81820362,  0.94315579],\n",
       "       [ 0.40938726,  0.1135109 , -0.23700942]])"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在进⾏矩阵计算时，经常需要⽤到该操作，⽐如利⽤np.dot计算矩阵内积：\n",
    "arr = np.random.randn(6,3)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10.29360187, -0.54630738,  6.92101476],\n",
       "       [-0.54630738,  9.21790268, -7.5055147 ],\n",
       "       [ 6.92101476, -7.5055147 , 12.08717954]])"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 计算矩阵内积\n",
    "np.dot(arr.T,arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7]],\n",
       "\n",
       "       [[ 8,  9, 10, 11],\n",
       "        [12, 13, 14, 15]]])"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对于⾼维数组，transpose需要得到⼀个由轴编号组成的元组才能对这些轴进⾏转置（⽐较费脑⼦）：\n",
    "arr = np.arange(16).reshape((2,2,4))\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  1,  2,  3],\n",
       "        [ 8,  9, 10, 11]],\n",
       "\n",
       "       [[ 4,  5,  6,  7],\n",
       "        [12, 13, 14, 15]]])"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 用transpose方法转置\n",
    "# 这⾥，第⼀个轴被换成了第⼆个，第⼆个轴被换成了第⼀个，最后⼀个轴不变。\n",
    "arr.transpose((1,0,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  1,  2,  3],\n",
       "        [ 4,  5,  6,  7]],\n",
       "\n",
       "       [[ 8,  9, 10, 11],\n",
       "        [12, 13, 14, 15]]])"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 简单的转置可以使⽤.T，它其实就是进⾏轴对换⽽已。ndarray还有⼀个swapaxes⽅法，它需要接受⼀对轴编号：\n",
    "# swapaxes也是返回源数据的视图（不会进⾏任何复制操作）。\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  4],\n",
       "        [ 1,  5],\n",
       "        [ 2,  6],\n",
       "        [ 3,  7]],\n",
       "\n",
       "       [[ 8, 12],\n",
       "        [ 9, 13],\n",
       "        [10, 14],\n",
       "        [11, 15]]])"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# swapaxes也是返回源数据的视图（不会进⾏任何复制操作）。\n",
    "arr.swapaxes(1,2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 4.2 通⽤函数：快速的元素级数组函数\n",
    "+ 通⽤函数（即ufunc）是⼀种对ndarray中的数据执⾏元素级运算\n",
    "的函数。\n",
    "+ 你可以将其看做简单函数（接受⼀个或多个标量值，并产⽣⼀个或多个标量值）的⽮量化包装器。\n",
    "+ 许多ufunc都是简单的元素级变体，如sqrt和exp：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(10)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.        , 1.        , 1.41421356, 1.73205081, 2.        ,\n",
       "       2.23606798, 2.44948974, 2.64575131, 2.82842712, 3.        ])"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,\n",
       "       5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,\n",
       "       2.98095799e+03, 8.10308393e+03])"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.exp(arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 这些都是⼀元（unary）ufunc。\n",
    "+ 另外⼀些（如add或maximum）\n",
    "接受2个数组（因此也叫⼆元（binary）ufunc），并返回⼀个结\n",
    "果数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.13320479, -0.45185469,  0.38841442, -1.05334311,  0.4673491 ,\n",
       "        1.24683874, -2.54171778, -1.29150909])"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.random.randn(8)\n",
    "y = np.random.randn(8)\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.45257942,  0.85049293,  1.27934842,  0.61765319,  0.45171509,\n",
       "        1.46687257,  1.10259571,  0.91140982])"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.13320479, 0.85049293, 1.27934842, 0.61765319, 0.4673491 ,\n",
       "       1.46687257, 1.10259571, 0.91140982])"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 这⾥，numpy.maximum计算了x和y中元素级别最⼤的元素。\n",
    "np.maximum(x,y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.88178507,  4.17675932,  1.52146989, -4.61337776, -1.71827045,\n",
       "       -6.80058533, -5.93453393])"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 虽然并不常⻅，但有些ufunc的确可以返回多个数组。\n",
    "# modf就是⼀个例⼦，它是Python内置函数divmod的⽮量化版本，它会返回浮点数数组的⼩数和整数部分：\n",
    "arr = np.random.randn(7) * 5\n",
    "arr\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [],
   "source": [
    "remainder,whole_part = np.modf(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.88178507,  0.17675932,  0.52146989, -0.61337776, -0.71827045,\n",
       "       -0.80058533, -0.93453393])"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "remainder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.,  4.,  1., -4., -1., -6., -5.])"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "whole_part"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 4.3 利⽤数组进⾏数据处理\n",
    "+ NumPy数组使你可以将许多种数据处理任务表述为简洁的数组\n",
    "表达式（否则需要编写循环）。\n",
    "+ ⽤数组表达式代替循环的做法，\n",
    "通常被称为⽮量化。\n",
    "+ ⼀般来说，⽮量化数组运算要⽐等价的纯\n",
    "Python⽅式快上⼀两个数量级（甚⾄更多），尤其是各种数值计\n",
    "算。\n",
    "+ 在后⾯内容中（⻅附录A）我将介绍⼴播，这是⼀种针对⽮\n",
    "量化计算的强⼤⼿段。\n",
    "+ 作为简单的例⼦，假设我们想要在⼀组值（⽹格型）上计算函\n",
    "数sqrt(x^2+y^2)。\n",
    "+ np.meshgrid函数接受两个⼀维数组，并产\n",
    "⽣两个⼆维矩阵（对应于两个数组中所有的(x,y)对）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-5.0000000e+00, -4.9900000e+00, -4.9800000e+00, -4.9700000e+00,\n",
       "       -4.9600000e+00, -4.9500000e+00, -4.9400000e+00, -4.9300000e+00,\n",
       "       -4.9200000e+00, -4.9100000e+00, -4.9000000e+00, -4.8900000e+00,\n",
       "       -4.8800000e+00, -4.8700000e+00, -4.8600000e+00, -4.8500000e+00,\n",
       "       -4.8400000e+00, -4.8300000e+00, -4.8200000e+00, -4.8100000e+00,\n",
       "       -4.8000000e+00, -4.7900000e+00, -4.7800000e+00, -4.7700000e+00,\n",
       "       -4.7600000e+00, -4.7500000e+00, -4.7400000e+00, -4.7300000e+00,\n",
       "       -4.7200000e+00, -4.7100000e+00, -4.7000000e+00, -4.6900000e+00,\n",
       "       -4.6800000e+00, -4.6700000e+00, -4.6600000e+00, -4.6500000e+00,\n",
       "       -4.6400000e+00, -4.6300000e+00, -4.6200000e+00, -4.6100000e+00,\n",
       "       -4.6000000e+00, -4.5900000e+00, -4.5800000e+00, -4.5700000e+00,\n",
       "       -4.5600000e+00, -4.5500000e+00, -4.5400000e+00, -4.5300000e+00,\n",
       "       -4.5200000e+00, -4.5100000e+00, -4.5000000e+00, -4.4900000e+00,\n",
       "       -4.4800000e+00, -4.4700000e+00, -4.4600000e+00, -4.4500000e+00,\n",
       "       -4.4400000e+00, -4.4300000e+00, -4.4200000e+00, -4.4100000e+00,\n",
       "       -4.4000000e+00, -4.3900000e+00, -4.3800000e+00, -4.3700000e+00,\n",
       "       -4.3600000e+00, -4.3500000e+00, -4.3400000e+00, -4.3300000e+00,\n",
       "       -4.3200000e+00, -4.3100000e+00, -4.3000000e+00, -4.2900000e+00,\n",
       "       -4.2800000e+00, -4.2700000e+00, -4.2600000e+00, -4.2500000e+00,\n",
       "       -4.2400000e+00, -4.2300000e+00, -4.2200000e+00, -4.2100000e+00,\n",
       "       -4.2000000e+00, -4.1900000e+00, -4.1800000e+00, -4.1700000e+00,\n",
       "       -4.1600000e+00, -4.1500000e+00, -4.1400000e+00, -4.1300000e+00,\n",
       "       -4.1200000e+00, -4.1100000e+00, -4.1000000e+00, -4.0900000e+00,\n",
       "       -4.0800000e+00, -4.0700000e+00, -4.0600000e+00, -4.0500000e+00,\n",
       "       -4.0400000e+00, -4.0300000e+00, -4.0200000e+00, -4.0100000e+00,\n",
       "       -4.0000000e+00, -3.9900000e+00, -3.9800000e+00, -3.9700000e+00,\n",
       "       -3.9600000e+00, -3.9500000e+00, -3.9400000e+00, -3.9300000e+00,\n",
       "       -3.9200000e+00, -3.9100000e+00, -3.9000000e+00, -3.8900000e+00,\n",
       "       -3.8800000e+00, -3.8700000e+00, -3.8600000e+00, -3.8500000e+00,\n",
       "       -3.8400000e+00, -3.8300000e+00, -3.8200000e+00, -3.8100000e+00,\n",
       "       -3.8000000e+00, -3.7900000e+00, -3.7800000e+00, -3.7700000e+00,\n",
       "       -3.7600000e+00, -3.7500000e+00, -3.7400000e+00, -3.7300000e+00,\n",
       "       -3.7200000e+00, -3.7100000e+00, -3.7000000e+00, -3.6900000e+00,\n",
       "       -3.6800000e+00, -3.6700000e+00, -3.6600000e+00, -3.6500000e+00,\n",
       "       -3.6400000e+00, -3.6300000e+00, -3.6200000e+00, -3.6100000e+00,\n",
       "       -3.6000000e+00, -3.5900000e+00, -3.5800000e+00, -3.5700000e+00,\n",
       "       -3.5600000e+00, -3.5500000e+00, -3.5400000e+00, -3.5300000e+00,\n",
       "       -3.5200000e+00, -3.5100000e+00, -3.5000000e+00, -3.4900000e+00,\n",
       "       -3.4800000e+00, -3.4700000e+00, -3.4600000e+00, -3.4500000e+00,\n",
       "       -3.4400000e+00, -3.4300000e+00, -3.4200000e+00, -3.4100000e+00,\n",
       "       -3.4000000e+00, -3.3900000e+00, -3.3800000e+00, -3.3700000e+00,\n",
       "       -3.3600000e+00, -3.3500000e+00, -3.3400000e+00, -3.3300000e+00,\n",
       "       -3.3200000e+00, -3.3100000e+00, -3.3000000e+00, -3.2900000e+00,\n",
       "       -3.2800000e+00, -3.2700000e+00, -3.2600000e+00, -3.2500000e+00,\n",
       "       -3.2400000e+00, -3.2300000e+00, -3.2200000e+00, -3.2100000e+00,\n",
       "       -3.2000000e+00, -3.1900000e+00, -3.1800000e+00, -3.1700000e+00,\n",
       "       -3.1600000e+00, -3.1500000e+00, -3.1400000e+00, -3.1300000e+00,\n",
       "       -3.1200000e+00, -3.1100000e+00, -3.1000000e+00, -3.0900000e+00,\n",
       "       -3.0800000e+00, -3.0700000e+00, -3.0600000e+00, -3.0500000e+00,\n",
       "       -3.0400000e+00, -3.0300000e+00, -3.0200000e+00, -3.0100000e+00,\n",
       "       -3.0000000e+00, -2.9900000e+00, -2.9800000e+00, -2.9700000e+00,\n",
       "       -2.9600000e+00, -2.9500000e+00, -2.9400000e+00, -2.9300000e+00,\n",
       "       -2.9200000e+00, -2.9100000e+00, -2.9000000e+00, -2.8900000e+00,\n",
       "       -2.8800000e+00, -2.8700000e+00, -2.8600000e+00, -2.8500000e+00,\n",
       "       -2.8400000e+00, -2.8300000e+00, -2.8200000e+00, -2.8100000e+00,\n",
       "       -2.8000000e+00, -2.7900000e+00, -2.7800000e+00, -2.7700000e+00,\n",
       "       -2.7600000e+00, -2.7500000e+00, -2.7400000e+00, -2.7300000e+00,\n",
       "       -2.7200000e+00, -2.7100000e+00, -2.7000000e+00, -2.6900000e+00,\n",
       "       -2.6800000e+00, -2.6700000e+00, -2.6600000e+00, -2.6500000e+00,\n",
       "       -2.6400000e+00, -2.6300000e+00, -2.6200000e+00, -2.6100000e+00,\n",
       "       -2.6000000e+00, -2.5900000e+00, -2.5800000e+00, -2.5700000e+00,\n",
       "       -2.5600000e+00, -2.5500000e+00, -2.5400000e+00, -2.5300000e+00,\n",
       "       -2.5200000e+00, -2.5100000e+00, -2.5000000e+00, -2.4900000e+00,\n",
       "       -2.4800000e+00, -2.4700000e+00, -2.4600000e+00, -2.4500000e+00,\n",
       "       -2.4400000e+00, -2.4300000e+00, -2.4200000e+00, -2.4100000e+00,\n",
       "       -2.4000000e+00, -2.3900000e+00, -2.3800000e+00, -2.3700000e+00,\n",
       "       -2.3600000e+00, -2.3500000e+00, -2.3400000e+00, -2.3300000e+00,\n",
       "       -2.3200000e+00, -2.3100000e+00, -2.3000000e+00, -2.2900000e+00,\n",
       "       -2.2800000e+00, -2.2700000e+00, -2.2600000e+00, -2.2500000e+00,\n",
       "       -2.2400000e+00, -2.2300000e+00, -2.2200000e+00, -2.2100000e+00,\n",
       "       -2.2000000e+00, -2.1900000e+00, -2.1800000e+00, -2.1700000e+00,\n",
       "       -2.1600000e+00, -2.1500000e+00, -2.1400000e+00, -2.1300000e+00,\n",
       "       -2.1200000e+00, -2.1100000e+00, -2.1000000e+00, -2.0900000e+00,\n",
       "       -2.0800000e+00, -2.0700000e+00, -2.0600000e+00, -2.0500000e+00,\n",
       "       -2.0400000e+00, -2.0300000e+00, -2.0200000e+00, -2.0100000e+00,\n",
       "       -2.0000000e+00, -1.9900000e+00, -1.9800000e+00, -1.9700000e+00,\n",
       "       -1.9600000e+00, -1.9500000e+00, -1.9400000e+00, -1.9300000e+00,\n",
       "       -1.9200000e+00, -1.9100000e+00, -1.9000000e+00, -1.8900000e+00,\n",
       "       -1.8800000e+00, -1.8700000e+00, -1.8600000e+00, -1.8500000e+00,\n",
       "       -1.8400000e+00, -1.8300000e+00, -1.8200000e+00, -1.8100000e+00,\n",
       "       -1.8000000e+00, -1.7900000e+00, -1.7800000e+00, -1.7700000e+00,\n",
       "       -1.7600000e+00, -1.7500000e+00, -1.7400000e+00, -1.7300000e+00,\n",
       "       -1.7200000e+00, -1.7100000e+00, -1.7000000e+00, -1.6900000e+00,\n",
       "       -1.6800000e+00, -1.6700000e+00, -1.6600000e+00, -1.6500000e+00,\n",
       "       -1.6400000e+00, -1.6300000e+00, -1.6200000e+00, -1.6100000e+00,\n",
       "       -1.6000000e+00, -1.5900000e+00, -1.5800000e+00, -1.5700000e+00,\n",
       "       -1.5600000e+00, -1.5500000e+00, -1.5400000e+00, -1.5300000e+00,\n",
       "       -1.5200000e+00, -1.5100000e+00, -1.5000000e+00, -1.4900000e+00,\n",
       "       -1.4800000e+00, -1.4700000e+00, -1.4600000e+00, -1.4500000e+00,\n",
       "       -1.4400000e+00, -1.4300000e+00, -1.4200000e+00, -1.4100000e+00,\n",
       "       -1.4000000e+00, -1.3900000e+00, -1.3800000e+00, -1.3700000e+00,\n",
       "       -1.3600000e+00, -1.3500000e+00, -1.3400000e+00, -1.3300000e+00,\n",
       "       -1.3200000e+00, -1.3100000e+00, -1.3000000e+00, -1.2900000e+00,\n",
       "       -1.2800000e+00, -1.2700000e+00, -1.2600000e+00, -1.2500000e+00,\n",
       "       -1.2400000e+00, -1.2300000e+00, -1.2200000e+00, -1.2100000e+00,\n",
       "       -1.2000000e+00, -1.1900000e+00, -1.1800000e+00, -1.1700000e+00,\n",
       "       -1.1600000e+00, -1.1500000e+00, -1.1400000e+00, -1.1300000e+00,\n",
       "       -1.1200000e+00, -1.1100000e+00, -1.1000000e+00, -1.0900000e+00,\n",
       "       -1.0800000e+00, -1.0700000e+00, -1.0600000e+00, -1.0500000e+00,\n",
       "       -1.0400000e+00, -1.0300000e+00, -1.0200000e+00, -1.0100000e+00,\n",
       "       -1.0000000e+00, -9.9000000e-01, -9.8000000e-01, -9.7000000e-01,\n",
       "       -9.6000000e-01, -9.5000000e-01, -9.4000000e-01, -9.3000000e-01,\n",
       "       -9.2000000e-01, -9.1000000e-01, -9.0000000e-01, -8.9000000e-01,\n",
       "       -8.8000000e-01, -8.7000000e-01, -8.6000000e-01, -8.5000000e-01,\n",
       "       -8.4000000e-01, -8.3000000e-01, -8.2000000e-01, -8.1000000e-01,\n",
       "       -8.0000000e-01, -7.9000000e-01, -7.8000000e-01, -7.7000000e-01,\n",
       "       -7.6000000e-01, -7.5000000e-01, -7.4000000e-01, -7.3000000e-01,\n",
       "       -7.2000000e-01, -7.1000000e-01, -7.0000000e-01, -6.9000000e-01,\n",
       "       -6.8000000e-01, -6.7000000e-01, -6.6000000e-01, -6.5000000e-01,\n",
       "       -6.4000000e-01, -6.3000000e-01, -6.2000000e-01, -6.1000000e-01,\n",
       "       -6.0000000e-01, -5.9000000e-01, -5.8000000e-01, -5.7000000e-01,\n",
       "       -5.6000000e-01, -5.5000000e-01, -5.4000000e-01, -5.3000000e-01,\n",
       "       -5.2000000e-01, -5.1000000e-01, -5.0000000e-01, -4.9000000e-01,\n",
       "       -4.8000000e-01, -4.7000000e-01, -4.6000000e-01, -4.5000000e-01,\n",
       "       -4.4000000e-01, -4.3000000e-01, -4.2000000e-01, -4.1000000e-01,\n",
       "       -4.0000000e-01, -3.9000000e-01, -3.8000000e-01, -3.7000000e-01,\n",
       "       -3.6000000e-01, -3.5000000e-01, -3.4000000e-01, -3.3000000e-01,\n",
       "       -3.2000000e-01, -3.1000000e-01, -3.0000000e-01, -2.9000000e-01,\n",
       "       -2.8000000e-01, -2.7000000e-01, -2.6000000e-01, -2.5000000e-01,\n",
       "       -2.4000000e-01, -2.3000000e-01, -2.2000000e-01, -2.1000000e-01,\n",
       "       -2.0000000e-01, -1.9000000e-01, -1.8000000e-01, -1.7000000e-01,\n",
       "       -1.6000000e-01, -1.5000000e-01, -1.4000000e-01, -1.3000000e-01,\n",
       "       -1.2000000e-01, -1.1000000e-01, -1.0000000e-01, -9.0000000e-02,\n",
       "       -8.0000000e-02, -7.0000000e-02, -6.0000000e-02, -5.0000000e-02,\n",
       "       -4.0000000e-02, -3.0000000e-02, -2.0000000e-02, -1.0000000e-02,\n",
       "       -1.0658141e-13,  1.0000000e-02,  2.0000000e-02,  3.0000000e-02,\n",
       "        4.0000000e-02,  5.0000000e-02,  6.0000000e-02,  7.0000000e-02,\n",
       "        8.0000000e-02,  9.0000000e-02,  1.0000000e-01,  1.1000000e-01,\n",
       "        1.2000000e-01,  1.3000000e-01,  1.4000000e-01,  1.5000000e-01,\n",
       "        1.6000000e-01,  1.7000000e-01,  1.8000000e-01,  1.9000000e-01,\n",
       "        2.0000000e-01,  2.1000000e-01,  2.2000000e-01,  2.3000000e-01,\n",
       "        2.4000000e-01,  2.5000000e-01,  2.6000000e-01,  2.7000000e-01,\n",
       "        2.8000000e-01,  2.9000000e-01,  3.0000000e-01,  3.1000000e-01,\n",
       "        3.2000000e-01,  3.3000000e-01,  3.4000000e-01,  3.5000000e-01,\n",
       "        3.6000000e-01,  3.7000000e-01,  3.8000000e-01,  3.9000000e-01,\n",
       "        4.0000000e-01,  4.1000000e-01,  4.2000000e-01,  4.3000000e-01,\n",
       "        4.4000000e-01,  4.5000000e-01,  4.6000000e-01,  4.7000000e-01,\n",
       "        4.8000000e-01,  4.9000000e-01,  5.0000000e-01,  5.1000000e-01,\n",
       "        5.2000000e-01,  5.3000000e-01,  5.4000000e-01,  5.5000000e-01,\n",
       "        5.6000000e-01,  5.7000000e-01,  5.8000000e-01,  5.9000000e-01,\n",
       "        6.0000000e-01,  6.1000000e-01,  6.2000000e-01,  6.3000000e-01,\n",
       "        6.4000000e-01,  6.5000000e-01,  6.6000000e-01,  6.7000000e-01,\n",
       "        6.8000000e-01,  6.9000000e-01,  7.0000000e-01,  7.1000000e-01,\n",
       "        7.2000000e-01,  7.3000000e-01,  7.4000000e-01,  7.5000000e-01,\n",
       "        7.6000000e-01,  7.7000000e-01,  7.8000000e-01,  7.9000000e-01,\n",
       "        8.0000000e-01,  8.1000000e-01,  8.2000000e-01,  8.3000000e-01,\n",
       "        8.4000000e-01,  8.5000000e-01,  8.6000000e-01,  8.7000000e-01,\n",
       "        8.8000000e-01,  8.9000000e-01,  9.0000000e-01,  9.1000000e-01,\n",
       "        9.2000000e-01,  9.3000000e-01,  9.4000000e-01,  9.5000000e-01,\n",
       "        9.6000000e-01,  9.7000000e-01,  9.8000000e-01,  9.9000000e-01,\n",
       "        1.0000000e+00,  1.0100000e+00,  1.0200000e+00,  1.0300000e+00,\n",
       "        1.0400000e+00,  1.0500000e+00,  1.0600000e+00,  1.0700000e+00,\n",
       "        1.0800000e+00,  1.0900000e+00,  1.1000000e+00,  1.1100000e+00,\n",
       "        1.1200000e+00,  1.1300000e+00,  1.1400000e+00,  1.1500000e+00,\n",
       "        1.1600000e+00,  1.1700000e+00,  1.1800000e+00,  1.1900000e+00,\n",
       "        1.2000000e+00,  1.2100000e+00,  1.2200000e+00,  1.2300000e+00,\n",
       "        1.2400000e+00,  1.2500000e+00,  1.2600000e+00,  1.2700000e+00,\n",
       "        1.2800000e+00,  1.2900000e+00,  1.3000000e+00,  1.3100000e+00,\n",
       "        1.3200000e+00,  1.3300000e+00,  1.3400000e+00,  1.3500000e+00,\n",
       "        1.3600000e+00,  1.3700000e+00,  1.3800000e+00,  1.3900000e+00,\n",
       "        1.4000000e+00,  1.4100000e+00,  1.4200000e+00,  1.4300000e+00,\n",
       "        1.4400000e+00,  1.4500000e+00,  1.4600000e+00,  1.4700000e+00,\n",
       "        1.4800000e+00,  1.4900000e+00,  1.5000000e+00,  1.5100000e+00,\n",
       "        1.5200000e+00,  1.5300000e+00,  1.5400000e+00,  1.5500000e+00,\n",
       "        1.5600000e+00,  1.5700000e+00,  1.5800000e+00,  1.5900000e+00,\n",
       "        1.6000000e+00,  1.6100000e+00,  1.6200000e+00,  1.6300000e+00,\n",
       "        1.6400000e+00,  1.6500000e+00,  1.6600000e+00,  1.6700000e+00,\n",
       "        1.6800000e+00,  1.6900000e+00,  1.7000000e+00,  1.7100000e+00,\n",
       "        1.7200000e+00,  1.7300000e+00,  1.7400000e+00,  1.7500000e+00,\n",
       "        1.7600000e+00,  1.7700000e+00,  1.7800000e+00,  1.7900000e+00,\n",
       "        1.8000000e+00,  1.8100000e+00,  1.8200000e+00,  1.8300000e+00,\n",
       "        1.8400000e+00,  1.8500000e+00,  1.8600000e+00,  1.8700000e+00,\n",
       "        1.8800000e+00,  1.8900000e+00,  1.9000000e+00,  1.9100000e+00,\n",
       "        1.9200000e+00,  1.9300000e+00,  1.9400000e+00,  1.9500000e+00,\n",
       "        1.9600000e+00,  1.9700000e+00,  1.9800000e+00,  1.9900000e+00,\n",
       "        2.0000000e+00,  2.0100000e+00,  2.0200000e+00,  2.0300000e+00,\n",
       "        2.0400000e+00,  2.0500000e+00,  2.0600000e+00,  2.0700000e+00,\n",
       "        2.0800000e+00,  2.0900000e+00,  2.1000000e+00,  2.1100000e+00,\n",
       "        2.1200000e+00,  2.1300000e+00,  2.1400000e+00,  2.1500000e+00,\n",
       "        2.1600000e+00,  2.1700000e+00,  2.1800000e+00,  2.1900000e+00,\n",
       "        2.2000000e+00,  2.2100000e+00,  2.2200000e+00,  2.2300000e+00,\n",
       "        2.2400000e+00,  2.2500000e+00,  2.2600000e+00,  2.2700000e+00,\n",
       "        2.2800000e+00,  2.2900000e+00,  2.3000000e+00,  2.3100000e+00,\n",
       "        2.3200000e+00,  2.3300000e+00,  2.3400000e+00,  2.3500000e+00,\n",
       "        2.3600000e+00,  2.3700000e+00,  2.3800000e+00,  2.3900000e+00,\n",
       "        2.4000000e+00,  2.4100000e+00,  2.4200000e+00,  2.4300000e+00,\n",
       "        2.4400000e+00,  2.4500000e+00,  2.4600000e+00,  2.4700000e+00,\n",
       "        2.4800000e+00,  2.4900000e+00,  2.5000000e+00,  2.5100000e+00,\n",
       "        2.5200000e+00,  2.5300000e+00,  2.5400000e+00,  2.5500000e+00,\n",
       "        2.5600000e+00,  2.5700000e+00,  2.5800000e+00,  2.5900000e+00,\n",
       "        2.6000000e+00,  2.6100000e+00,  2.6200000e+00,  2.6300000e+00,\n",
       "        2.6400000e+00,  2.6500000e+00,  2.6600000e+00,  2.6700000e+00,\n",
       "        2.6800000e+00,  2.6900000e+00,  2.7000000e+00,  2.7100000e+00,\n",
       "        2.7200000e+00,  2.7300000e+00,  2.7400000e+00,  2.7500000e+00,\n",
       "        2.7600000e+00,  2.7700000e+00,  2.7800000e+00,  2.7900000e+00,\n",
       "        2.8000000e+00,  2.8100000e+00,  2.8200000e+00,  2.8300000e+00,\n",
       "        2.8400000e+00,  2.8500000e+00,  2.8600000e+00,  2.8700000e+00,\n",
       "        2.8800000e+00,  2.8900000e+00,  2.9000000e+00,  2.9100000e+00,\n",
       "        2.9200000e+00,  2.9300000e+00,  2.9400000e+00,  2.9500000e+00,\n",
       "        2.9600000e+00,  2.9700000e+00,  2.9800000e+00,  2.9900000e+00,\n",
       "        3.0000000e+00,  3.0100000e+00,  3.0200000e+00,  3.0300000e+00,\n",
       "        3.0400000e+00,  3.0500000e+00,  3.0600000e+00,  3.0700000e+00,\n",
       "        3.0800000e+00,  3.0900000e+00,  3.1000000e+00,  3.1100000e+00,\n",
       "        3.1200000e+00,  3.1300000e+00,  3.1400000e+00,  3.1500000e+00,\n",
       "        3.1600000e+00,  3.1700000e+00,  3.1800000e+00,  3.1900000e+00,\n",
       "        3.2000000e+00,  3.2100000e+00,  3.2200000e+00,  3.2300000e+00,\n",
       "        3.2400000e+00,  3.2500000e+00,  3.2600000e+00,  3.2700000e+00,\n",
       "        3.2800000e+00,  3.2900000e+00,  3.3000000e+00,  3.3100000e+00,\n",
       "        3.3200000e+00,  3.3300000e+00,  3.3400000e+00,  3.3500000e+00,\n",
       "        3.3600000e+00,  3.3700000e+00,  3.3800000e+00,  3.3900000e+00,\n",
       "        3.4000000e+00,  3.4100000e+00,  3.4200000e+00,  3.4300000e+00,\n",
       "        3.4400000e+00,  3.4500000e+00,  3.4600000e+00,  3.4700000e+00,\n",
       "        3.4800000e+00,  3.4900000e+00,  3.5000000e+00,  3.5100000e+00,\n",
       "        3.5200000e+00,  3.5300000e+00,  3.5400000e+00,  3.5500000e+00,\n",
       "        3.5600000e+00,  3.5700000e+00,  3.5800000e+00,  3.5900000e+00,\n",
       "        3.6000000e+00,  3.6100000e+00,  3.6200000e+00,  3.6300000e+00,\n",
       "        3.6400000e+00,  3.6500000e+00,  3.6600000e+00,  3.6700000e+00,\n",
       "        3.6800000e+00,  3.6900000e+00,  3.7000000e+00,  3.7100000e+00,\n",
       "        3.7200000e+00,  3.7300000e+00,  3.7400000e+00,  3.7500000e+00,\n",
       "        3.7600000e+00,  3.7700000e+00,  3.7800000e+00,  3.7900000e+00,\n",
       "        3.8000000e+00,  3.8100000e+00,  3.8200000e+00,  3.8300000e+00,\n",
       "        3.8400000e+00,  3.8500000e+00,  3.8600000e+00,  3.8700000e+00,\n",
       "        3.8800000e+00,  3.8900000e+00,  3.9000000e+00,  3.9100000e+00,\n",
       "        3.9200000e+00,  3.9300000e+00,  3.9400000e+00,  3.9500000e+00,\n",
       "        3.9600000e+00,  3.9700000e+00,  3.9800000e+00,  3.9900000e+00,\n",
       "        4.0000000e+00,  4.0100000e+00,  4.0200000e+00,  4.0300000e+00,\n",
       "        4.0400000e+00,  4.0500000e+00,  4.0600000e+00,  4.0700000e+00,\n",
       "        4.0800000e+00,  4.0900000e+00,  4.1000000e+00,  4.1100000e+00,\n",
       "        4.1200000e+00,  4.1300000e+00,  4.1400000e+00,  4.1500000e+00,\n",
       "        4.1600000e+00,  4.1700000e+00,  4.1800000e+00,  4.1900000e+00,\n",
       "        4.2000000e+00,  4.2100000e+00,  4.2200000e+00,  4.2300000e+00,\n",
       "        4.2400000e+00,  4.2500000e+00,  4.2600000e+00,  4.2700000e+00,\n",
       "        4.2800000e+00,  4.2900000e+00,  4.3000000e+00,  4.3100000e+00,\n",
       "        4.3200000e+00,  4.3300000e+00,  4.3400000e+00,  4.3500000e+00,\n",
       "        4.3600000e+00,  4.3700000e+00,  4.3800000e+00,  4.3900000e+00,\n",
       "        4.4000000e+00,  4.4100000e+00,  4.4200000e+00,  4.4300000e+00,\n",
       "        4.4400000e+00,  4.4500000e+00,  4.4600000e+00,  4.4700000e+00,\n",
       "        4.4800000e+00,  4.4900000e+00,  4.5000000e+00,  4.5100000e+00,\n",
       "        4.5200000e+00,  4.5300000e+00,  4.5400000e+00,  4.5500000e+00,\n",
       "        4.5600000e+00,  4.5700000e+00,  4.5800000e+00,  4.5900000e+00,\n",
       "        4.6000000e+00,  4.6100000e+00,  4.6200000e+00,  4.6300000e+00,\n",
       "        4.6400000e+00,  4.6500000e+00,  4.6600000e+00,  4.6700000e+00,\n",
       "        4.6800000e+00,  4.6900000e+00,  4.7000000e+00,  4.7100000e+00,\n",
       "        4.7200000e+00,  4.7300000e+00,  4.7400000e+00,  4.7500000e+00,\n",
       "        4.7600000e+00,  4.7700000e+00,  4.7800000e+00,  4.7900000e+00,\n",
       "        4.8000000e+00,  4.8100000e+00,  4.8200000e+00,  4.8300000e+00,\n",
       "        4.8400000e+00,  4.8500000e+00,  4.8600000e+00,  4.8700000e+00,\n",
       "        4.8800000e+00,  4.8900000e+00,  4.9000000e+00,  4.9100000e+00,\n",
       "        4.9200000e+00,  4.9300000e+00,  4.9400000e+00,  4.9500000e+00,\n",
       "        4.9600000e+00,  4.9700000e+00,  4.9800000e+00,  4.9900000e+00])"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "points = np.arange(-5,5,0.01)  # 1000个\n",
    "points"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-5.  , -5.  , -5.  , ..., -5.  , -5.  , -5.  ],\n",
       "       [-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],\n",
       "       [-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],\n",
       "       ...,\n",
       "       [ 4.97,  4.97,  4.97, ...,  4.97,  4.97,  4.97],\n",
       "       [ 4.98,  4.98,  4.98, ...,  4.98,  4.98,  4.98],\n",
       "       [ 4.99,  4.99,  4.99, ...,  4.99,  4.99,  4.99]])"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xs, ys = np.meshgrid(points,points)\n",
    "ys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       ...,\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99],\n",
       "       [-5.  , -4.99, -4.98, ...,  4.97,  4.98,  4.99]])"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[7.07106781, 7.06400028, 7.05693985, ..., 7.04988652, 7.05693985,\n",
       "        7.06400028],\n",
       "       [7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,\n",
       "        7.05692568],\n",
       "       [7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,\n",
       "        7.04985815],\n",
       "       ...,\n",
       "       [7.04988652, 7.04279774, 7.03571603, ..., 7.0286414 , 7.03571603,\n",
       "        7.04279774],\n",
       "       [7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,\n",
       "        7.04985815],\n",
       "       [7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,\n",
       "        7.05692568]])"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 现在，对该函数的求值运算就好办了，把这两个数组当做两个浮点数那样编写表达式即可：\n",
    "z = np.sqrt(xs**2 + ys**2)\n",
    "z"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig =plt.figure()\n",
    "\n",
    "\n",
    "ax = fig.add_subplot(221)\n",
    "ax.imshow(z)\n",
    "\n",
    "ax = fig.add_subplot(222)\n",
    "ax.imshow(z,cmap=plt.cm.gray)\n",
    "\n",
    "ax = fig.add_subplot(223)\n",
    "ax.imshow(z,cmap=plt.cm.cool)\n",
    "\n",
    "ax = fig.add_subplot(224)\n",
    "ax.imshow(z,cmap=plt.cm.hot)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 将条件逻辑表述为数组运算\n",
    "+ numpy.where函数是三元表达式x if condition else y的⽮量化版\n",
    "本。\n",
    "+ 假设我们有⼀个布尔数组和两个值数组："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {},
   "outputs": [],
   "source": [
    "xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])\n",
    "yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])\n",
    "cond = np.array([True, False, True, True, False])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.1, 2.2, 1.3, 1.4, 2.5])"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 假设我们想要根据cond中的值选取xarr和yarr的值：\n",
    "# 当cond中的值为True时，选取xarr的值，否则从yarr中选取。\n",
    "# 列表推导式的写法 比较复杂，且运行速度较慢\n",
    "# 可以使用numpy.where\n",
    "result = np.where(cond, xarr, yarr)\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.29464411, -0.74196317, -1.48244695, -0.27393942],\n",
       "       [-0.66400027,  0.09846747,  0.94920927,  0.82805639],\n",
       "       [ 0.50946501, -0.01471214, -0.4571586 ,  0.4495547 ],\n",
       "       [ 0.66083028, -0.55576035,  0.21568549, -1.26980739]])"
      ]
     },
     "execution_count": 134,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# np.where的第⼆个和第三个参数不必是数组，它们都可以是标量值。\n",
    "# 在数据分析⼯作中，where通常⽤于根据另⼀个数组⽽产⽣⼀个新的数组。\n",
    "# 假设有⼀个由随机数据组成的矩阵，你希望将所有正值替换为2，将所有负值替换为－2。\n",
    "# 若利⽤np.where，则会⾮常简单：\n",
    "arr = np.random.randn(4,4)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False, False, False, False],\n",
       "       [False,  True,  True,  True],\n",
       "       [ True, False, False,  True],\n",
       "       [ True, False,  True, False]])"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr > 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-2, -2, -2, -2],\n",
       "       [-2,  2,  2,  2],\n",
       "       [ 2, -2, -2,  2],\n",
       "       [ 2, -2,  2, -2]])"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 用2替代正值，-2替代负值\n",
    "np.where(arr > 0, 2, -2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.29464411, -0.74196317, -1.48244695, -0.27393942],\n",
       "       [-0.66400027,  2.        ,  2.        ,  2.        ],\n",
       "       [ 2.        , -0.01471214, -0.4571586 ,  2.        ],\n",
       "       [ 2.        , -0.55576035,  2.        , -1.26980739]])"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 只用2替换掉正值\n",
    "np.where(arr > 0, 2, arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 数学和统计⽅法\n",
    "可以通过数组上的⼀组数学函数对整个数组或某个轴向的数据进\n",
    "⾏统计计算。\n",
    "+ sum、mean以及标准差std等聚合计算\n",
    "（aggregation，通常叫做约简（reduction））既可以当做数组\n",
    "的实例⽅法调⽤，也可以当做顶级NumPy函数使⽤。\n",
    "+ 这⾥，我⽣成了⼀些正态分布随机数据，然后做了聚类统计："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.11988057,  1.958673  ,  1.27105279, -0.19229241],\n",
       "       [ 0.02695267,  0.33811422, -1.33686303,  1.13414907],\n",
       "       [ 1.14660905, -0.96564017,  1.17799168,  1.72567105],\n",
       "       [ 0.73886617, -2.14184076, -0.50563258,  0.0506261 ],\n",
       "       [-1.04211774, -1.37377964,  0.57067118,  0.50504282]])"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(5, 4)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.21030670285824163"
      ]
     },
     "execution_count": 141,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.21030670285824163"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.mean(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.2061340571648325"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.2061340571648325"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sum(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.03932849,  0.04058824,  0.7711579 , -0.46449527, -0.33504584])"
      ]
     },
     "execution_count": 146,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# mean和sum这类的函数可以接受⼀个axis选项参数，⽤于计算该轴向上的统计值，最终结果是⼀个少⼀维的数组：\n",
    "# 这⾥，arr.mean(1)是“计算⾏的平均值”，arr.sum(0)是“计算每列的和”。\n",
    "\n",
    "arr.mean(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.39803814, -0.43689467,  0.23544401,  0.64463933])"
      ]
     },
     "execution_count": 147,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.mean(axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 4.15731395,  0.16235294,  3.08463161, -1.85798107, -1.34018338])"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sum(axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.99019072, -2.18447335,  1.17722005,  3.22319663])"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sum(axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7])"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 其他如cumsum和cumprod之类的⽅法则不聚合，⽽是产⽣⼀个由中间结果组成的数组：\n",
    "arr = np.array([0,1,2,3,4,5,6,7])\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  3,  6, 10, 15, 21, 28], dtype=int32)"
      ]
     },
     "execution_count": 151,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在多维数组中，累加函数（如cumsum）返回的是同样⼤⼩的数组，但是会根据每个低维的切⽚沿着标记轴计算部分聚类：\n",
    "arr.cumsum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 152,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2],\n",
       "       [3, 4, 5],\n",
       "       [6, 7, 8]])"
      ]
     },
     "execution_count": 152,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在多维数组中，累加函数（如cumsum）返回的是同样⼤⼩的数组，但是会根据每个低维的切⽚沿着标记轴计算部分聚类：\n",
    "arr = np.array([[0,1,2],[3,4,5],[6,7,8]])\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 154,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  2],\n",
       "       [ 3,  5,  7],\n",
       "       [ 9, 12, 15]], dtype=int32)"
      ]
     },
     "execution_count": 154,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.cumsum(axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  0,   0,   0],\n",
       "       [  3,  12,  60],\n",
       "       [  6,  42, 336]], dtype=int32)"
      ]
     },
     "execution_count": 158,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.cumprod(axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ ⽤于布尔型数组的⽅法\n",
    "+ 在上⾯这些⽅法中，布尔值会被强制转换为1（True）和\n",
    "0（False）。\n",
    "+ 因此，sum经常被⽤来对布尔型数组中的True值计\n",
    "数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "63"
      ]
     },
     "execution_count": 161,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(100)\n",
    "(arr > 0).sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 另外还有两个⽅法any和all，它们对布尔型数组⾮常有⽤。\n",
    "# any⽤于测试数组中是否存在⼀个或多个True，⽽all则检查数组中所有值是否都是True：\n",
    "# 这两个⽅法也能⽤于⾮布尔型数组，所有⾮0元素将会被当做True。\n",
    "\n",
    "bools = np.array([False,True,True,False,False,False])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 163,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bools.any()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 164,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bools.all()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 排序\n",
    "+ 跟Python内置的列表类型⼀样，NumPy数组也可以通过sort⽅法\n",
    "就地排序："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 169,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.57527142, -1.5863591 , -1.09762629,  0.09877113, -0.56087873,\n",
       "        0.24252281])"
      ]
     },
     "execution_count": 169,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(6)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 171,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.5863591 , -1.09762629, -0.56087873,  0.09877113,  0.24252281,\n",
       "        0.57527142])"
      ]
     },
     "execution_count": 171,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sort()\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 172,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.96105048,  1.23320683, -0.36596499],\n",
       "       [-1.01864787,  1.49416397, -1.07636807],\n",
       "       [ 0.27665496, -0.15781648,  1.90145004],\n",
       "       [-0.53498203,  1.10288081, -0.95514065],\n",
       "       [ 0.01091928, -0.46751584,  1.10880463]])"
      ]
     },
     "execution_count": 172,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 多维数组可以在任何⼀个轴向上进⾏排序，只需将轴编号传给sort即可：\n",
    "arr = np.random.randn(5,3)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 173,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.96105048, -0.36596499,  1.23320683],\n",
       "       [-1.07636807, -1.01864787,  1.49416397],\n",
       "       [-0.15781648,  0.27665496,  1.90145004],\n",
       "       [-0.95514065, -0.53498203,  1.10288081],\n",
       "       [-0.46751584,  0.01091928,  1.10880463]])"
      ]
     },
     "execution_count": 173,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sort(1)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.07636807, -1.01864787,  1.10288081],\n",
       "       [-0.96105048, -0.53498203,  1.10880463],\n",
       "       [-0.95514065, -0.36596499,  1.23320683],\n",
       "       [-0.46751584,  0.01091928,  1.49416397],\n",
       "       [-0.15781648,  0.27665496,  1.90145004]])"
      ]
     },
     "execution_count": 175,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sort(0)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 179,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 顶级⽅法np.sort返回的是数组的已排序副本，⽽就地排序则会修改数组本身。\n",
    "# 计算数组分位数最简单的办法是对其进⾏排序，然后选取特定位置的值：\n",
    "large_arr =\tnp.random.randn(1000)\n",
    "large_arr.sort()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 181,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1000"
      ]
     },
     "execution_count": 181,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(large_arr) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 182,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "50"
      ]
     },
     "execution_count": 182,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int(0.05 * len(large_arr))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 183,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.6177792838412313"
      ]
     },
     "execution_count": 183,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "large_arr[int(0.05 * len(large_arr))]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 唯⼀化以及其它的集合逻辑\n",
    "NumPy提供了⼀些针对⼀维ndarray的基本集合运算。\n",
    "+ 最常⽤的\n",
    "可能要数np.unique了，它⽤于找出数组中的唯⼀值并返回已排\n",
    "序的结果：\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+ 4.4 ⽤于数组的⽂件输⼊输出\n",
    "+ NumPy能够读写磁盘上的⽂本数据或⼆进制数据。\n",
    "+ 这⼀⼩节只\n",
    "讨论NumPy的内置⼆进制格式，因为更多的⽤户会使⽤pandas\n",
    "或其它⼯具加载⽂本或表格数据（⻅第6章）。\n",
    "+ np.save和np.load是读写磁盘数组数据的两个主要函数。\n",
    "+ 默认情\n",
    "况下，数组是以未压缩的原始⼆进制格式保存在扩展名为.npy的\n",
    "⽂件中的："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "hide_input": false,
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
